package multiclient;



//Set up a Server that will receive a connection
//from a client, send a string to the client,
//and close the connection.

//Java core packages
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
//Java extension packages
import javax.swing.*;
public class Server extends JFrame {
	private static JTextField enterField;
	private static JTextArea displayArea;
	private static ServerSocket server;	
	private static int counter = 0;
	protected static Multi[] m = new Multi[10];
	ArrayList<Socket> clientsockets = new ArrayList<Socket>(10);
	// set up GUI
	public Server()
	{
		super( "Server" );

		Container container = getContentPane();

		// create enterField and register listener
		enterField = new JTextField();
		enterField.setEnabled( false );
		container.add( enterField, BorderLayout.NORTH );

		// create displayArea
		displayArea = new JTextArea();
		container.add( new JScrollPane( displayArea ),
				BorderLayout.CENTER );
		setSize( 400, 250 );
		setVisible( true );
	}
	// execute application
	public static void main( String args[] ) throws IOException
	{
		new Server();
		server = new ServerSocket( 5000, 100 );
		while(true) {
			for (int i = 0; i < 10; i++) {
				if (m[i]==null) {
			new Thread(m[i] = new Multi( m,server.accept(), displayArea, enterField)).start(); 
			counter++;	System.out.println(counter);
			break;
				}
		  }	
		}
	}
	static class Multi extends Thread implements ActionListener{
		protected Multi[] m;
		protected 	Socket connection;
		protected  JTextArea displayArea;
		protected  JTextField enterField;
		protected  ObjectOutputStream output = null;
		protected  ObjectInputStream input = null;
		public Multi(Multi[] m,Socket client, JTextArea a, JTextField t){
			this.m = m;
			this.connection = client;
			this.displayArea = a;
			this.enterField = t;
			this.enterField.addActionListener(this);
			
		}
		public void run(){
			this.runServer();
		}
		

		// set up and run server
		public void runServer()
		{
			// set up server to receive connections;
			// process connections
			try {
				// Step 1: Create a ServerSocket.			
				this.getStreams();
				while ( true ) {

					// Step 3: Get input and output streams.
				

					// Step 4: Process connection.
					this.processConnection();
					//this.closeConnection();
					// Step 5: Close connection.
					//closeConnection();

					++counter;
				}
			}

			// process EOFException when client closes connection
			catch ( EOFException eofException ) {
				System.out.println( "Client terminated connection" );
			}

			// process problems with I/O
			catch ( IOException ioException ) {
				ioException.printStackTrace();
			}
		}

		// wait for connection to arrive, then display connection info
		

		// get streams to send and receive data
		protected void getStreams() throws IOException
		{
			// set up output stream for objects
			output = new ObjectOutputStream(
					connection.getOutputStream() );

			// set up input stream for objects
			input = new ObjectInputStream(
					connection.getInputStream() );

			displayArea.append( "\nGot I/O streams\n" );
		}

		// process connection with client
		protected void processConnection() throws IOException
		{
			// send connection successful message to client
			String message = "SERVER>>> Connection successful from : "+connection.getRemoteSocketAddress();
//			for (int i = 0; i < m.length; i++) {
//			if (m[i]!= null && i %2 ==0 && i>0) {m[i-1].output.writeObject( message ); m[i-1].output.flush(); break; }
//			else if (m[i]!= null && i % 2 > 0) {
//			m[i+1].output.writeObject( message ); m[i+1].output.flush(); break;}	
//			}
			//output.flush();

			// enable enterField so server user can send messages
			enterField.setEnabled( true );

			// process messages sent from client
			

				// read message and display it
				try {
					message = ( String ) input.readObject();
					displayArea.append( "\n" + message );
					displayArea.setCaretPosition(
					displayArea.getText().length() );
				}

				// catch problems reading from client
				catch ( ClassNotFoundException classNotFoundException ) {
					displayArea.append( "\nUnknown object type received" );
				}
				catch (SocketException e) { 
					displayArea.append( "Conexao perdida :"+connection.getRemoteSocketAddress());
				//	closeConnection();
					}
			
		}
		// close streams and socket
		protected void closeConnection() throws IOException
		{
			enterField.setText("");
			input.close(); input = null;
			output.close(); output = null;
			connection.close(); connection = null;
			for (int i = 0; i < m.length; i++) {
				if (m[i]==this) m[i]=null;  
			}
//				try {
//				if (connection != null) connection.close( );
//				}
//				catch (IOException e) {}
//								
		}
		// send message to client
		public void sendData( String message )
		{
			// send object to client
			try {
				for (int i = 0; i < m.length & m[i]!= null; i++) {
					m[i].output.writeObject( message ); m[i].output.flush(); 	
					}
				displayArea.append("\nSERVER>>> "+message);
				enterField.setText(null);
			}

			// process problems sending object
			catch ( IOException ioException ) {
				displayArea.append( "\nError writing object" );
				
			}
		}
		
		protected void finalize() throws Throwable {
			this.closeConnection();
	
		}	
		public void actionPerformed(ActionEvent arg0) {
		sendData(enterField.getText());	
		}
	}
} // end class Server